package com.baoyouqun.base.handler;

import cn.dev33.satoken.exception.*;
import com.alibaba.cola.dto.Response;
import com.alibaba.cola.dto.SingleResponse;
import com.fasterxml.jackson.databind.exc.InvalidFormatException;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;

import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.List;

@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {


    // 处理容器级别的文件大小超限（若配置的max-file-size被触发）
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public Response handleMaxUploadSize(MaxUploadSizeExceededException e) {
        long maxSize = 10 * 1024 * 1024; // 与配置和业务层保持一致
        return Response.buildFailure("400", "文件大小超过限制，最大支持" + maxSize / (1024 * 1024) + "MB");
    }


    @ExceptionHandler(RuntimeException.class)
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    public Response handleRuntimeException(RuntimeException e, HttpServletRequest request) {
        log.error("捕获运行时异常，URL:{}，异常类型:{}，消息:{}",
                request.getRequestURI(),
                e.getClass().getName(),  // 打印具体异常类型
                e.getMessage(),
                e); // 打印堆栈
        return Response.buildFailure("10002", "操作失败：" + e.getMessage());
    }


    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    public Response handleIllegalArgumentException(IllegalArgumentException e) {
        log.warn("非法参数异常", e);
        // 枚举校验失败时，异常消息通常包含无效值信息，直接返回
        return Response.buildFailure("10004", "参数无效：" + e.getMessage());
    }

    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    @ResponseStatus(value = HttpStatus.NOT_ACCEPTABLE)
    public Response exceptionHandler(HttpRequestMethodNotSupportedException e) {
        String failMsg = e.getMessage();
        log.warn("HttpRequestMethodNotSupportedException", e);
        return Response.buildFailure("10101", failMsg);
    }


    @ResponseStatus(value = HttpStatus.UNAUTHORIZED)
    @ExceptionHandler(NotLoginException.class)
    public Response handlerNotLoginException(NotLoginException e) {
//        log.warn("NotLoginException", e);
        // 不同异常返回不同状态码
        String message = "";
        if (e.getType().equals(NotLoginException.NOT_TOKEN)) {
            message = "当前会话未登录，请先进行登录";
        } else if (e.getType().equals(NotLoginException.INVALID_TOKEN)) {
            message = "当前会话未登录，请先进行登录";
        } else if (e.getType().equals(NotLoginException.TOKEN_TIMEOUT)) {
            message = "登录信息已过期，请重新登录";
        } else if (e.getType().equals(NotLoginException.BE_REPLACED)) {
            message = "您的账户已在另一台设备上登录，如非本人操作，请立即修改密码";
        } else if (e.getType().equals(NotLoginException.KICK_OUT)) {
            message = "已被系统强制下线";
        } else {
            message = "当前会话未登录，请先进行登录";
        }
        // 返回给前端
        return Response.buildFailure("401", message);
    }

    @ResponseStatus(value = HttpStatus.FORBIDDEN)
    @ExceptionHandler
    public Response handlerNotSafeException(NotSafeException e) {
        log.warn("NotSafeException", e);
        SingleResponse response = SingleResponse.buildFailure("402", "二级认证异常");
        response.setData("二级认证异常：" + e.getMessage());
        return response;
//        return Response.buildFailure("401", "二级认证异常：" + e.getMessage());
    }

    @ResponseStatus(value = HttpStatus.FORBIDDEN)
    @ExceptionHandler
    public Response handlerNotRoleException(NotRoleException e) {
        log.warn("NotRoleException", e);
        SingleResponse<String> response = SingleResponse.buildFailure("403", "没有权限");
        response.setData("无此角色：" + e.getRole());
        return response;
//        return Response.buildFailure("403", "无此角色：" + e.getRole());
    }

    @ResponseStatus(value = HttpStatus.FORBIDDEN)
    @ExceptionHandler(NotPermissionException.class)
    public Response handlerNotPermissionException(NotPermissionException e) {
        log.warn("NotPermissionException", e);
        SingleResponse<String> response = SingleResponse.buildFailure("403", "没有权限");
        response.setData("无此权限：" + e.getPermission());
        return response;
    }

    @ResponseStatus(value = HttpStatus.UNAUTHORIZED)
    @ExceptionHandler
    public Response handlerDisableLoginException(DisableServiceException e) {
        log.warn("DisableServiceException", e);
        return Response.buildFailure("401", "账户被封禁：" + e.getDisableTime() + "秒后解封");
    }


    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public Response handleThrowable(HttpMessageNotReadableException e, HttpServletRequest request) {
        log.warn("HttpMessageNotReadableException", e);
        log.warn("URL:{} ,系统异常: ｛｝", request.getRequestURI(), e);
        Throwable rootCause = e.getRootCause();
        //日期格式转换异常
        if (rootCause instanceof DateTimeParseException) {
            String errorMessage = String.format("时间格式不合规异常：{%s}", ((DateTimeParseException) rootCause).getParsedString());
            return Response.buildFailure("100031", errorMessage);
        }
        // 无效格式异常处理。比如：目标格式为数值，输入为非数字的字符串（"80.5%"、"8.5.1"、"张三"）。
        if (rootCause instanceof InvalidFormatException) {
            String errorMessage = String.format("无效格式异常：{%s}", rootCause.getMessage());
            return Response.buildFailure("100032", errorMessage);
        }
        String errorMessage = "Http消息不可读异常(" + rootCause + ")";
        return Response.buildFailure("10003", errorMessage);
    }


    @ExceptionHandler(Throwable.class)
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    public Response handleThrowable(Throwable e, HttpServletRequest request) {
        log.warn("HttpServletRequest", e);
        log.warn("URL:{} ,系统异常: {}", request.getRequestURI(), e);
        return Response.buildFailure("10000", "系统异常");
    }


    // 专门处理参数验证异常
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody // 返回JSON格式
    public Response handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        BindingResult bindingResult = e.getBindingResult();
        List<String> errorMessages = new ArrayList<>();

        // 提取所有错误提示信息到列表
        for (FieldError fieldError : bindingResult.getFieldErrors()) {
            errorMessages.add(fieldError.getDefaultMessage());
        }

        // 用逗号拼接错误信息（无方括号）
        String errMsg = String.join(", ", errorMessages);

        // 返回封装后的错误响应
        return Response.buildFailure("10256", errMsg);
    }
}

